from enum import StrEnum, Enum
from typing import Union


class SystemVariableKey(StrEnum):
    """
    System Variables.
    """

    QUERY = "query"
    FILES = "files"
    CONVERSATION_ID = "conversation_id"
    USER_ID = "user_id"
    DIALOGUE_COUNT = "dialogue_count"
    APP_ID = "app_id"
    WORKFLOW_ID = "workflow_id"
    WORKFLOW_EXECUTION_ID = "workflow_run_id"

class UserFrom(StrEnum):
    ACCOUNT = "account"
    END_USER = "end-user"


class InvokeFrom(Enum):
    """
    Invoke From.
    """

    SERVICE_API = "service-api"
    WEB_APP = "web-app"
    EXPLORE = "explore"
    DEBUGGER = "debugger"

    @classmethod
    def value_of(cls, value: str):
        """
        Get value of given mode.

        :param value: mode value
        :return: mode
        """
        for mode in cls:
            if mode.value == value:
                return mode
        raise ValueError(f"invalid invoke from value {value}")

    def to_source(self) -> str:
        """
        Get source of invoke from.

        :return: source
        """
        if self == InvokeFrom.WEB_APP:
            return "web_app"
        elif self == InvokeFrom.DEBUGGER:
            return "dev"
        elif self == InvokeFrom.EXPLORE:
            return "explore_app"
        elif self == InvokeFrom.SERVICE_API:
            return "api"

        return "dev"

    class WorkflowType(Enum):
        """
        Workflow Type Enum
        """

        WORKFLOW = "workflow"
        CHAT = "chat"

        @classmethod
        def value_of(cls, value: str) -> "WorkflowType":
            """
            Get value of given mode.

            :param value: mode value
            :return: mode
            """
            for mode in cls:
                if mode.value == value:
                    return mode
            raise ValueError(f"invalid workflow type value {value}")

        @classmethod
        def from_app_mode(cls, app_mode: Union[str, "AppMode"]) -> "WorkflowType":
            """
            Get workflow type from app mode.

            :param app_mode: app mode
            :return: workflow type
            """
            from models.model import AppMode

            app_mode = app_mode if isinstance(app_mode, AppMode) else AppMode.value_of(app_mode)
            return cls.WORKFLOW if app_mode == AppMode.WORKFLOW else cls.CHAT
